#region Copyright (c) 2006-2009 Widgetsphere LLC, All Rights Reserved
//--------------------------------------------------------------------- *
//                          Widgetsphere  LLC                           *
//             Copyright (c) 2006-2009 All Rights reserved              *
//                                                                      *
//                                                                      *
//This file and its contents are protected by United States and         *
//International copyright laws.  Unauthorized reproduction and/or       *
//distribution of all or any portion of the code contained herein       *
//is strictly prohibited and will result in severe civil and criminal   *
//penalties.  Any violations of this copyright will be prosecuted       *
//to the fullest extent possible under law.                             *
//                                                                      *
//THE SOURCE CODE CONTAINED HEREIN AND IN RELATED FILES IS PROVIDED     *
//TO THE REGISTERED DEVELOPER FOR THE PURPOSES OF EDUCATION AND         *
//TROUBLESHOOTING. UNDER NO CIRCUMSTANCES MAY ANY PORTION OF THE SOURCE *
//CODE BE DISTRIBUTED, DISCLOSED OR OTHERWISE MADE AVAILABLE TO ANY     *
//THIRD PARTY WITHOUT THE EXPRESS WRITTEN CONSENT OF WIDGETSPHERE LLC   *
//                                                                      *
//UNDER NO CIRCUMSTANCES MAY THE SOURCE CODE BE USED IN WHOLE OR IN     *
//PART, AS THE BASIS FOR CREATING A PRODUCT THAT PROVIDES THE SAME, OR  *
//SUBSTANTIALLY THE SAME, FUNCTIONALITY AS ANY WIDGETSPHERE PRODUCT.    *
//                                                                      *
//THE REGISTERED DEVELOPER ACKNOWLEDGES THAT THIS SOURCE CODE           *
//CONTAINS VALUABLE AND PROPRIETARY TRADE SECRETS OF WIDGETSPHERE,      *
//INC.  THE REGISTERED DEVELOPER AGREES TO EXPEND EVERY EFFORT TO       *
//INSURE ITS CONFIDENTIALITY.                                           *
//                                                                      *
//THE END USER LICENSE AGREEMENT (EULA) ACCOMPANYING THE PRODUCT        *
//PERMITS THE REGISTERED DEVELOPER TO REDISTRIBUTE THE PRODUCT IN       *
//EXECUTABLE FORM ONLY IN SUPPORT OF APPLICATIONS WRITTEN USING         *
//THE PRODUCT.  IT DOES NOT PROVIDE ANY RIGHTS REGARDING THE            *
//SOURCE CODE CONTAINED HEREIN.                                         *
//                                                                      *
//THIS COPYRIGHT NOTICE MAY NOT BE REMOVED FROM THIS FILE.              *
//--------------------------------------------------------------------- *
#endregion
using System;
using System.Collections;
using System.Xml;
using System.ComponentModel;
using Widgetsphere.Generator.Common.Util;
using Widgetsphere.Generator.Common.GeneratorFramework;
using Widgetsphere.Generator.ProjectItemGenerators;

namespace Widgetsphere.Generator.Models
{
  public enum IdentityTypeConstants
  {
    None,
    Database,
    Code,
  }

  public class Column : BaseModelObject, ICodeFacadeObject
  {
    #region Member Variables

    protected const System.Data.SqlDbType _def_type = System.Data.SqlDbType.VarChar;
    protected const int _def_length = 1;
    protected const bool _def_primaryKey = false;
    protected const IdentityTypeConstants _def_identity = IdentityTypeConstants.None;
    protected const bool _def_codeImplementedIdentity = false;
    protected const bool _def_allowNull = true;
		protected const bool _def_generated = true;
    protected const int _def_sortOrder = 0;
    protected const bool _def_gridVisible = false;
		protected const string _def_mask = "";
		protected const double _def_min = double.NaN;
		protected const double _def_max = double.NaN;
		protected const bool _def_isSearchable = false;
		protected const bool _def_isIndexed = false;
		protected const bool _def_isUnique = false;

    protected int _id = 0;
    protected string _name = "";
    protected string _codeFacade = "";
    protected string _description = "";
    protected System.Data.SqlDbType _type = _def_type;
    protected int _length = _def_length;
    protected bool _primaryKey = _def_primaryKey;
		protected bool _generated = _def_generated;
		protected IdentityTypeConstants _identity = _def_identity;
    protected bool _allowNull = _def_allowNull;
    protected string _default = "";
    protected Reference _parentTableRef = null;
    protected Reference _relationshipRef = null;
    private string _enumType = "";
    private string _friendlyName = "";
    private int _sortOrder = _def_sortOrder;
    private bool _gridVisible = _def_gridVisible;
		private string _mask = _def_mask;
		private double _min = _def_min;
    private double _max = _def_max;
		private bool _isSearchable = _def_isSearchable;
		private bool _isIndexed = _def_isIndexed;
		private DateTime _createdDate = DateTime.Now;
		protected bool _isUnique = _def_isUnique;

		#endregion

    #region Constructor

    public Column(IModelObject root)
      : base(root)
    {
    }

    #endregion

    #region Property Implementations

    [
    Browsable(true),
    Description("Determine if this column is the table primary key."),
    Category("Data"),
    DefaultValue(_def_primaryKey),
    ]
    public bool PrimaryKey
    {
      get { return _primaryKey; }
      set
      {
        _primaryKey = value;
        this.OnPropertyChanged(this, new PropertyChangedEventArgs("primaryKey"));
      }
    }


		[
		Browsable(true),
		Description("Determines if this item is used in the generation."),
		Category("Data"),
		DefaultValue(_def_generated),
		]
		public bool Generated
		{
			get { return _generated; }
			set
			{
				_generated = value;
				this.OnPropertyChanged(this, new PropertyChangedEventArgs("generated"));
			}
		}

    [
    Browsable(true),
    Description("Determines the type of identity for this column."),
    Category("Data"),
    DefaultValue(_def_identity),
    ]
    public IdentityTypeConstants Identity
    {
      get { return _identity; }
      set
      {
        _identity = value;
        this.OnPropertyChanged(this, new PropertyChangedEventArgs("Identity"));
      }
    }

    [
    Browsable(true),
    Description("Determines the name of this column."),
    Category("Design"),
    DefaultValue(""),
    ]
    public string Name
    {
      get { return _name; }
      set
      {
        _name = value;
        this.OnPropertyChanged(this, new PropertyChangedEventArgs("Name"));
      }
    }

    [
    Browsable(true),
    Description("Determines description text were applicable."),
    Category("Data"),
    DefaultValue(""),
    ]
    public string Description
    {
      get { return _description; }
      set
      {
        _description = value;
        this.OnPropertyChanged(this, new PropertyChangedEventArgs("Description"));
      }
    }

    [Browsable(false)]
    public Reference RelationshipRef
    {
      get { return _relationshipRef; }
      set { _relationshipRef = value; }
    }

    [
    Browsable(true),
    Description("Determines the default value of this column."),
    Category("Data"),
    DefaultValue(""),
    ]
    public string Default
    {
      get { return _default; }
      set
      {
        _default = value;
        this.OnPropertyChanged(this, new PropertyChangedEventArgs("Default"));
      }
    }

    [
    Browsable(true),
		Description("Determines the size of this column in bytes."),
    Category("Data"),
    DefaultValue(_def_length),
    ]
    public int Length
    {
      get
      {
        int retval = this.GetPredefinedSize();
        if (retval == -1) retval = _length;
        return retval;
      }
      set
      {
        if (value <= 0) value = 1;
        _length = value;
        this.OnPropertyChanged(this, new PropertyChangedEventArgs("Length"));
      }
    }

		[
		Browsable(true),
		Description("Determines the minimum value for a int, long, float value."),
		Category("Data"),
		DefaultValue(_def_min),
		]
		public double Min
		{
			get { return _min; }
			set
			{
				_min = value;
				this.OnPropertyChanged(this, new PropertyChangedEventArgs("Min"));
			}
		}

    [
    Browsable(true),
    Description("Determines the maximum value for a int, long, float value."),
    Category("Data"),
    DefaultValue(_def_max),
    ]
    public double Max
    {
      get { return _max; }
      set
      {
        _max = value;
        this.OnPropertyChanged(this, new PropertyChangedEventArgs("Max"));
      }
    }

    [
    Browsable(true),
    Description("Determines if this field can be used in searches. When true, a custom method will be generated in the API to select by this field."),
    Category("Data"),
    DefaultValue(_def_isSearchable),
    ]
    public bool IsSearchable
    {
      get { return _isSearchable; }
      set
      {
        _isSearchable = value;
        this.OnPropertyChanged(this, new PropertyChangedEventArgs("IsSearchable"));
      }
    }

		[
		Browsable(true),
		Description("Determines if this field has a database index."),
		Category("Data"),
		DefaultValue(_def_isIndexed),
		]
		public bool IsIndexed
		{
			get { return _isIndexed || _isSearchable; }
			set
			{
				_isIndexed = value;
				this.OnPropertyChanged(this, new PropertyChangedEventArgs("IsIndexed"));
			}
		}

		[
		Browsable(true),
		Description("Determines if this field is marked as unique."),
		Category("Data"),
		DefaultValue(_def_isUnique),
		]
		public bool IsUnique
		{
			get { return _isUnique || _primaryKey; }
			set
			{
				_isUnique = value;
				this.OnPropertyChanged(this, new PropertyChangedEventArgs("IsUnique"));
			}
		}		
		
		[Browsable(false)]
    public int Id
    {
      get { return _id; }
    }

    [Browsable(false)]
    public Reference ParentTableRef
    {
      get { return _parentTableRef; }
      set { _parentTableRef = value; }
    }

    [
    Browsable(true),
    Description("Determines the data type of this column."),
    Category("Data"),
    DefaultValue(System.Data.SqlDbType.VarChar),
    ]
    public System.Data.SqlDbType Type
    {
      get { return _type; }
      set
      {
				if (!Column.IsSupportedType(value))
				{
					throw new Exception("Unsupported type");
				}
        _type = value;
        this.OnPropertyChanged(this, new PropertyChangedEventArgs("Type"));
      }
    }

    [
    Browsable(true),
    Description("Determines if this column allows null values."),
    Category("Data"),
    DefaultValue(_def_allowNull),
    ]
    public bool AllowNull
    {
      get { return _allowNull; }
      set
      {
        _allowNull = value;
        this.OnPropertyChanged(this, new PropertyChangedEventArgs("allowNull"));
      }
    }

    /// <summary>
    /// Determines the header text shown to users, if this column is visible in data grid displays.
    /// </summary>
    [
    Browsable(false),
    Description("Determines the header text shown to users, if this column is visible in data grid displays."),
    Category("Appearance"),
    ]
    public string FriendlyName
    {
      get { return _friendlyName; }
      set
      {
        _friendlyName = value;
        this.OnPropertyChanged(this, new PropertyChangedEventArgs("friendlyName"));
      }
    }

    /// <summary>
    /// Determines the sort order of this field in relation to other data visible fields.
    /// </summary>
    [
		Browsable(false),
    Description("Determines the sort order of this field in relation to other data visible fields."),
    Category("Appearance"),
    DefaultValue(_def_sortOrder),
    ]
    public int SortOrder
    {
      get { return _sortOrder; }
      set
      {
        _sortOrder = value;
        this.OnPropertyChanged(this, new PropertyChangedEventArgs("sortOrder"));
      }
    }

    /// <summary>
    /// Determines if the column is visible in grids.
    /// </summary>
    [
		Browsable(false),
    Description("Determines if the column is visible in grids."),
    Category("Appearance"),
    DefaultValue(_def_gridVisible),
    ]
    public bool GridVisible
    {
      get { return _gridVisible; }
      set
      {
        _gridVisible = value;
        this.OnPropertyChanged(this, new PropertyChangedEventArgs("gridVisible"));
      }
    }

		/// <summary>
		/// Identifies the mask for data input.
		/// </summary>
		[
		Browsable(false),
		Description("Identifies the mask for data input and presentation."),
		Category("Mask"),
		DefaultValue(_def_mask),
		]
		public string Mask
		{
			get { return _mask; }
			set
			{
				_mask = value;
				this.OnPropertyChanged(this, new PropertyChangedEventArgs("mask"));
			}
		}

    internal string DatabaseType
    {
			get
			{
				string retval = this.Type.ToString();
				if (Globals.IsTextType(this.Type))
					retval += "(" + this.Length + ")"; ;
				return retval;
			}
    }

		/// <summary>
		/// Determines if this field type can be made into a range query
		/// </summary>
		internal bool IsRangeType
		{
			get
			{
				switch (this.Type)
				{
					case System.Data.SqlDbType.BigInt:
					//case System.Data.SqlDbType.Char:
					case System.Data.SqlDbType.Date:
					case System.Data.SqlDbType.DateTime:
					case System.Data.SqlDbType.DateTime2:
					case System.Data.SqlDbType.Decimal:
					case System.Data.SqlDbType.Float:
					case System.Data.SqlDbType.Int:
					case System.Data.SqlDbType.Money:
					//case System.Data.SqlDbType.NChar:
					//case System.Data.SqlDbType.NVarChar:
					case System.Data.SqlDbType.Real:
					case System.Data.SqlDbType.SmallDateTime:
					case System.Data.SqlDbType.SmallInt:
					case System.Data.SqlDbType.SmallMoney:
					case System.Data.SqlDbType.Time:
					case System.Data.SqlDbType.TinyInt:
					//case System.Data.SqlDbType.VarChar:
						return true;
				}
				return false;
			}
		}

		[Browsable(true)]
		[Category("Data")]
		[Description("The date that this object was created.")]
		[ReadOnlyAttribute(true)]
		public DateTime CreatedDate
		{
			get { return _createdDate; }
		}

		[Browsable(false)]
		public string CorePropertiesHash
		{
			get
			{
				string prehash = this.Name + "|" +
					this.Identity + "|" +
					this.AllowNull + "|" +
					this.Default + "|" +
					this.Length + "|" +
					this.PrimaryKey + "|" +
					this.Type.ToString();
				//return HashHelper.Hash(prehash);
				return prehash;
			}
		}

		[Browsable(false)]
		public string CorePropertiesHashNoPK
		{
			get
			{
				string prehash = this.Name + "|" +
					this.Identity + "|" +
					this.AllowNull + "|" +
					this.Default + "|" +
					this.Length + "|" +					
					this.Type.ToString();
				//return HashHelper.Hash(prehash);
				return prehash;
			}
		}	

		#endregion

    #region Methods

    public override string ToString()
    {
      string sizeString = "";
      if (this.GetPredefinedSize() == -1)
        sizeString = "(" + this.Length + ")";

      string retval = this.Name;
			//if (this.CodeFacade != "")
			//  retval += " AS " + this.CodeFacade;
			return retval;

      //retval += " (" + this.Type.ToString().ToLower() + sizeString + ", " + (this.AllowNull ? "Null" : "Not Null") + ")";
      //return retval;
    }

		/// <summary>
		/// Determine if the specified type is 
		/// </summary>
		/// <param name="type"></param>
		/// <returns></returns>
		public static bool IsSupportedType(System.Data.SqlDbType type)
		{
			switch (type)
			{
				case System.Data.SqlDbType.Xml:
				case System.Data.SqlDbType.Udt:
				case System.Data.SqlDbType.Structured:
				case System.Data.SqlDbType.DateTimeOffset:
				case System.Data.SqlDbType.DateTime2:
				case System.Data.SqlDbType.Time:
				case System.Data.SqlDbType.Date:
					return false;
				default:
					return true;
			}
		}

    #endregion

    #region IXMLable Members

    public override void XmlAppend(XmlNode node)
    {
      try
      {
        XmlDocument oDoc = node.OwnerDocument;

        XmlAttribute keyNode = oDoc.CreateAttribute("key");
        keyNode.Value = this.Key.ToString();
        node.Attributes.Append(keyNode);

        XmlAttribute primaryKey = oDoc.CreateAttribute("primaryKey");
        primaryKey.Value = this.PrimaryKey.ToString();
        node.Attributes.Append(primaryKey);

				XmlHelper.AddAttribute((XmlElement)node, "generated", Generated.ToString());
				
				XmlAttribute identity = oDoc.CreateAttribute("identity");
        identity.Value = this.Identity.ToString("d");
        node.Attributes.Append(identity);

        XmlAttribute name = oDoc.CreateAttribute("name");
        name.Value = this.Name;
        node.Attributes.Append(name);
        
        XmlAttribute codefacade = oDoc.CreateAttribute("codeFacade");
        codefacade.Value = this.CodeFacade;
        node.Attributes.Append(codefacade);

        XmlAttribute description = oDoc.CreateAttribute("description");
        description.Value = this.Description;
        node.Attributes.Append(description);

        XmlAttribute dataFieldFriendlyName = oDoc.CreateAttribute("dataFieldFriendlyName");
        dataFieldFriendlyName.Value = this.FriendlyName;
        node.Attributes.Append(dataFieldFriendlyName);

        XmlAttribute dataFieldVisibility = oDoc.CreateAttribute("dataFieldVisibility");
        dataFieldVisibility.Value = this.GridVisible.ToString();
        node.Attributes.Append(dataFieldVisibility);

        XmlAttribute dataFieldSortOrder = oDoc.CreateAttribute("dataFieldSortOrder");
        dataFieldSortOrder.Value = this.SortOrder.ToString();
        node.Attributes.Append(dataFieldSortOrder);

        if(RelationshipRef != null)
        {
          XmlNode relationshipRefNode = oDoc.CreateElement("relationshipRef");
          RelationshipRef.XmlAppend(relationshipRefNode);
          node.AppendChild(relationshipRefNode);
        }

        XmlAttribute defaultVal = oDoc.CreateAttribute("default");
        defaultVal.Value = this.Default;
        node.Attributes.Append(defaultVal);

        XmlAttribute length = oDoc.CreateAttribute("length");
        length.Value = this.Length.ToString();
        node.Attributes.Append(length);

				XmlAttribute isIndexed = oDoc.CreateAttribute("isIndexed");
				isIndexed.Value = this.IsIndexed.ToString();
				node.Attributes.Append(isIndexed);

				XmlAttribute isUnique = oDoc.CreateAttribute("isUnique");
				isUnique.Value = this.IsUnique.ToString();
				node.Attributes.Append(isUnique);
				
				XmlAttribute id = oDoc.CreateAttribute("id");
        id.Value = this.Id.ToString();
        node.Attributes.Append(id);

        XmlNode parentTableRefNode = oDoc.CreateElement("parentTableRef");
        ParentTableRef.XmlAppend(parentTableRefNode);
        node.AppendChild(parentTableRefNode);

        XmlAttribute type = oDoc.CreateAttribute("type");
        type.Value = this.Type.ToString("d");
        node.Attributes.Append(type);

        XmlAttribute allowNull = oDoc.CreateAttribute("allowNull");
        allowNull.Value = this.AllowNull.ToString();
        node.Attributes.Append(allowNull);

				XmlAttribute min = oDoc.CreateAttribute("min");
				min.Value = this.Min.ToString();
				node.Attributes.Append(min);

				XmlAttribute max = oDoc.CreateAttribute("max");
				max.Value = this.Max.ToString();
				node.Attributes.Append(max);

        XmlAttribute isSearchable = oDoc.CreateAttribute("isSearchable");
        isSearchable.Value = this.IsSearchable.ToString();
        node.Attributes.Append(isSearchable);
        
        XmlAttribute mask = oDoc.CreateAttribute("mask");
				mask.Value = this.Mask.ToString();
				node.Attributes.Append(mask);

				XmlAttribute created = oDoc.CreateAttribute("createdDate");
				created.Value = _createdDate.ToString("yyyy-MM-dd HH:mm:ss");
				node.Attributes.Append(created);

      }
      catch (Exception ex)
      {
        throw;
      }
    }

    public override void XmlLoad(XmlNode node)
    {
      try
      {
        _key = XmlHelper.GetAttributeValue(node, "key", _key);
        this.PrimaryKey = bool.Parse(node.Attributes["primaryKey"].Value);
				this.Generated = bool.Parse(XmlHelper.GetAttributeValue(node, "generated", _def_generated.ToString()));
        this.Identity = (IdentityTypeConstants)int.Parse(node.Attributes["identity"].Value);
        this.Name = node.Attributes["name"].Value;
        this.CodeFacade = XmlHelper.GetAttributeValue(node, "codeFacade", "");
        this.Description = node.Attributes["description"].Value;
        this.FriendlyName = XmlHelper.GetAttributeValue(node, "dataFieldFriendlyName", this.FriendlyName);
        this.GridVisible = bool.Parse(XmlHelper.GetAttributeValue(node, "dataFieldVisibility", this.GridVisible.ToString()));
        this.SortOrder = int.Parse(XmlHelper.GetAttributeValue(node, "dataFieldSortOrder", this.SortOrder.ToString()));
				this.Min = double.Parse(XmlHelper.GetAttributeValue(node, "min", _def_min.ToString()));
				this.Max = double.Parse(XmlHelper.GetAttributeValue(node, "max", _def_max.ToString()));
				this.Mask = XmlHelper.GetAttributeValue(node, "mask", _def_mask);
				_createdDate = DateTime.ParseExact(XmlHelper.GetAttributeValue(node, "createdDate", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")), "yyyy-MM-dd HH:mm:ss", System.Globalization.CultureInfo.InvariantCulture);
        this.IsSearchable = bool.Parse(XmlHelper.GetAttributeValue(node, "isSearchable", this.IsSearchable.ToString()));
				this.IsIndexed = bool.Parse(XmlHelper.GetAttributeValue(node, "isIndexed", this.IsIndexed.ToString()));
				this.IsUnique = bool.Parse(XmlHelper.GetAttributeValue(node, "isUnique", this.IsUnique.ToString()));
				XmlNode relationshipRefNode = node.SelectSingleNode("relationshipRef");
        if (relationshipRefNode != null)
        {
          RelationshipRef = new Reference(this.Root);
          RelationshipRef.XmlLoad(relationshipRefNode);
        }

        string defaultValue = node.Attributes["default"].Value;
				defaultValue = defaultValue.Replace("\n", "");
				defaultValue = defaultValue.Replace("\r", "");
				this.Default = defaultValue;

        this.Length = int.Parse(node.Attributes["length"].Value);
        this.SetId(int.Parse(node.Attributes["id"].Value));

        XmlNode parentTableRefNode = node.SelectSingleNode("parentTableRef");
        ParentTableRef = new Reference(this.Root);
        ParentTableRef.XmlLoad(parentTableRefNode);

        string typeString = node.Attributes["type"].Value;
        if (typeString != "")
          this.Type = (System.Data.SqlDbType)int.Parse(typeString);

        this.AllowNull = bool.Parse(XmlHelper.GetAttributeValue(node, "allowNull", "false"));

        this.Dirty = false;
      }
      catch (Exception ex)
      {
        throw;
      }

    }

    #endregion

    #region Helpers

    public Reference CreateRef()
    {
      Reference returnVal = new Reference(this.Root);
      returnVal.Ref = this.Id;
      returnVal.RefType = ReferenceType.Column;
      return returnVal;
    }

    [Browsable(false)]
    public string CamelName
    {
      //get { return StringHelper.DatabaseNameToCamelCase(this.Name); }
			get { return StringHelper.DatabaseNameToCamelCase(this.PascalName); }
    }

		[Browsable(false)]
		public string PascalName
		{
			get
			{
				if (this.CodeFacade != "")
					return StringHelper.DatabaseNameToPascalCase(this.CodeFacade);
				else
					return StringHelper.DatabaseNameToPascalCase(this.Name);
			}
		}

    [Browsable(false)]
    public string DatabaseName
    {
      get { return this.Name; }
    }

    internal string EnumType
    {
      get { return _enumType; }
      set { _enumType = value; }
    }

		public string GetSQLDefaultType()
		{
			string retval = this.Type.ToString();

			if (StringHelper.Match(this.Type, "binary", true) ||
				StringHelper.Match(this.Type, "char", true) ||
				StringHelper.Match(this.Type, "decimal", true) ||
				StringHelper.Match(this.Type, "nchar", true) ||
				StringHelper.Match(this.Type, "numeric", true) ||
				StringHelper.Match(this.Type, "nvarchar", true) ||
				StringHelper.Match(this.Type, "varbinary", true) ||
				StringHelper.Match(this.Type, "varchar", true))
			{
				if (StringHelper.Match(this.Type, "decimal", true))
				{
					retval += "(" + this.Length + ",2)";
				}
				else
				{
					retval += "(" + this.Length + ")";
				}
			}

			return retval;

		}

		public string GetCodeType()
		{
			return GetCodeType(true, false);
		}

		public string GetCodeType(bool allowNullable)
		{
			return GetCodeType(allowNullable, false);
		}

		public string GetCodeType(bool allowNullable, bool forceNull)
		{
			string retval = "";
			if (this.EnumType != "")
			{
				retval = this.EnumType;
			}
			else if (StringHelper.Match(this.Type.ToString(), "bigint", true))
			{
				retval = "long";
			}
			else if (StringHelper.Match(this.Type.ToString(), "binary", true))
			{
				return "System.Byte[]";
			}
			else if (StringHelper.Match(this.Type.ToString(), "bit", true))
			{
				retval = "bool";
			}
			else if (StringHelper.Match(this.Type.ToString(), "char", true))
			{
				return "string";
			}
			else if (StringHelper.Match(this.Type.ToString(), "datetime", true))
			{
				retval = "DateTime";
			}
			else if (StringHelper.Match(this.Type.ToString(), "decimal", true))
			{
				retval = "decimal";
			}
			else if (StringHelper.Match(this.Type.ToString(), "float", true))
			{
				retval = "double";
			}
			else if (StringHelper.Match(this.Type.ToString(), "image", true))
			{
				return "System.Byte[]";
			}
			else if (StringHelper.Match(this.Type.ToString(), "int", true))
			{
				retval = "int";
			}
			else if (StringHelper.Match(this.Type.ToString(), "money", true))
			{
				retval = "decimal";
			}
			else if (StringHelper.Match(this.Type.ToString(), "nchar", true))
			{
				return "string";
			}
			else if (StringHelper.Match(this.Type.ToString(), "ntext", true))
			{
				return "string";
			}
			else if (StringHelper.Match(this.Type.ToString(), "numeric", true))
			{
				retval = "decimal";
			}
			else if (StringHelper.Match(this.Type.ToString(), "nvarchar", true))
			{
				return "string";
			}
			else if (StringHelper.Match(this.Type.ToString(), "real", true))
			{
				retval = "System.Single";
			}
			else if (StringHelper.Match(this.Type.ToString(), "smalldatetime", true))
			{
				retval = "DateTime";
			}
			else if (StringHelper.Match(this.Type.ToString(), "smallint", true))
			{
				retval = "short";
			}
			else if (StringHelper.Match(this.Type.ToString(), "smallmoney", true))
			{
				retval = "decimal";
			}				
			else if (StringHelper.Match(this.Type.ToString(), "variant", true))
			{
				retval = "object";
			}
			else if (StringHelper.Match(this.Type.ToString(), "text", true))
			{
				return "string";
			}
			else if (StringHelper.Match(this.Type.ToString(), "tinyint", true))
			{
				retval = "byte";
			}
			else if (StringHelper.Match(this.Type.ToString(), "uniqueidentifier", true))
			{
				retval = "System.Guid";
			}
			else if (StringHelper.Match(this.Type.ToString(), "varbinary", true))
			{
				return "System.Byte[]";
			}
			else if (StringHelper.Match(this.Type.ToString(), "varchar", true))
			{
				return "string";
			}
			else if (StringHelper.Match(this.Type.ToString(), "timestamp", true))
			{
				return "System.Byte[]";
			}
			else
			{
				throw new Exception("Cannot Map Sql Value To C# Value");
			}

			if (allowNullable && (this.AllowNull || forceNull))
				retval += "?";

			return retval;

		}

    /// <summary>
    /// Determines if the Datatype suppors the 'Parse' method
    /// </summary>
    [Browsable(false)]
    public bool AllowStringParse
    {
      get
      {
        if(StringHelper.Match(this.Type.ToString(), "bigint", true))
        {
          return true;
        }
        else if(StringHelper.Match(this.Type.ToString(), "binary", true))
        {
          return false;
        }
        else if(StringHelper.Match(this.Type.ToString(), "bit", true))
        {
          return true;
        }
        else if(StringHelper.Match(this.Type.ToString(), "char", true))
        {
          return false;
        }
        else if(StringHelper.Match(this.Type.ToString(), "datetime", true))
        {
          return true;
        }
        else if(StringHelper.Match(this.Type.ToString(), "decimal", true))
        {
          return true;
        }
        else if(StringHelper.Match(this.Type.ToString(), "float", true))
        {
          return true;
        }
        else if(StringHelper.Match(this.Type.ToString(), "image", true))
        {
          return false;
        }
        else if(StringHelper.Match(this.Type.ToString(), "int", true))
        {
          return true;
        }
        else if(StringHelper.Match(this.Type.ToString(), "money", true))
        {
          return true;
        }
        else if(StringHelper.Match(this.Type.ToString(), "nchar", true))
        {
          return false;
        }
        else if(StringHelper.Match(this.Type.ToString(), "ntext", true))
        {
          return false;
        }
        else if(StringHelper.Match(this.Type.ToString(), "numeric", true))
        {
          return true;
        }
        else if(StringHelper.Match(this.Type.ToString(), "nvarchar", true))
        {
          return false;
        }
        else if(StringHelper.Match(this.Type.ToString(), "real", true))
        {
          return true;
        }
        else if(StringHelper.Match(this.Type.ToString(), "smalldatetime", true))
        {
          return true;
        }
        else if(StringHelper.Match(this.Type.ToString(), "smallint", true))
        {
          return true;
        }
        else if(StringHelper.Match(this.Type.ToString(), "smallmoney", true))
        {
          return true;
        }
        else if(StringHelper.Match(this.Type.ToString(), "variant", true))
        {
          return false;
        }
        else if(StringHelper.Match(this.Type.ToString(), "text", true))
        {
          return false;
        }
        else if(StringHelper.Match(this.Type.ToString(), "tinyint", true))
        {
          return false;
        }
        else if(StringHelper.Match(this.Type.ToString(), "uniqueidentifier", true))
        {
          return false;
        }
        else if(StringHelper.Match(this.Type.ToString(), "varbinary", true))
        {
          return false;
        }
        else if(StringHelper.Match(this.Type.ToString(), "varchar", true))
        {
          return false;
        }
        else if(StringHelper.Match(this.Type.ToString(), "timestamp", true))
        {
          return false;
        }
        else
        {
          return false;
        }
      }
    }

    protected internal void SetId(int id)
    {
      _id = id;
    }

		protected internal void SetKey(string key)
		{
			_key = key;
		}

    public int GetPredefinedSize()
    {
      //Returns -1 if variable
      switch(this.Type)
      {
        case System.Data.SqlDbType.BigInt:
          return 8;
        case System.Data.SqlDbType.Bit:
          return 1;
        case System.Data.SqlDbType.DateTime:
          return 8;
        case System.Data.SqlDbType.Decimal:
          return 13;
        case System.Data.SqlDbType.Float:
          return 8;
        case System.Data.SqlDbType.Int:
          return 4;
        case System.Data.SqlDbType.Money:
          return 8;
        case System.Data.SqlDbType.Real:
          return 4;
        case System.Data.SqlDbType.SmallDateTime:
          return 4;
        case System.Data.SqlDbType.SmallInt:
          return 2;
        case System.Data.SqlDbType.SmallMoney:
          return 4;
        case System.Data.SqlDbType.Timestamp:
          return 8;
        case System.Data.SqlDbType.TinyInt:
          return 1;
        case System.Data.SqlDbType.UniqueIdentifier:
          return 16;
        default:
          return -1;
      }
    }

    #endregion

    #region ICodeFacadeObject Members

    [
    Browsable(true),
    Description("Determines the object name used in the API. If this property is blank the 'Name' property is used in the API. This property can be used to mask the database identifier."),
    Category("Design"),
    DefaultValue(""),
    ]
    public string CodeFacade
    {
      get { return _codeFacade; }
      set
      {
        _codeFacade = value;
        this.OnPropertyChanged(this, new PropertyChangedEventArgs("codeFacade"));
      }
    }

    public string GetCodeFacade()
    {
      if (this.CodeFacade == "")
        return this.Name;
      else
        return this.CodeFacade;
    }

    #endregion

  }
}